package edu.ou.herbarium.main;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

import org.apache.catalina.util.MD5Encoder;
import org.apache.commons.codec.binary.Hex;
import org.hibernate.Transaction;

import edu.ou.herbarium.data.HibernateSessionFactory;
import edu.ou.herbarium.service.Authority;
import edu.ou.herbarium.service.Collector;
import edu.ou.herbarium.service.CollectorDAO;
import edu.ou.herbarium.service.Folder;
import edu.ou.herbarium.service.FolderDAO;
import edu.ou.herbarium.service.ImageRaw;
import edu.ou.herbarium.service.ImageRawDAO;
import edu.ou.herbarium.service.SpecCollectorMap;
import edu.ou.herbarium.service.SpecCollectorMapDAO;
import edu.ou.herbarium.service.Specimen;
import edu.ou.herbarium.service.SpecimenDAO;
import edu.ou.herbarium.service.User;
import edu.ou.herbarium.service.UserAuthorityMap;
import edu.ou.herbarium.service.UserAuthorityMapDAO;
import edu.ou.herbarium.service.UserDAO;
import edu.ou.herbarium.utils.ImageUtils;
import edu.ou.herbarium.utils.ImageUtils2;

public class DataUtils {
	public static String ports="";
	public static String SERVER_DIR = "C:/apache-tomcat-7.0.33/webapps/HerbService/img/"; 
	public static String FULL_IMAGE_NAME = "full.jpg";
	public static String THUMB_IMAGE_NAME = "full_3.jpg";
	public static String THUMB_IMAGE_NAME_2 = "full_4.jpg";
	public static String DISPLAY_IMAGE_NAME = "full_2.jpg";
	public Folder getTopFolders(){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
    	FolderDAO folderDao = new FolderDAO();
    	List<Folder> topFolders = folderDao.findByProperty("folderId", "1");
    	topFolders.get(0).getFolders();
    	topFolders.get(0).getSpecimens();
    	for(Specimen spec : topFolders.get(0).getSpecimens()){
    		spec.getImageRaw();
    		Set<SpecCollectorMap> mapSet = spec.getSpecCollectorMaps();
    		for(SpecCollectorMap map : mapSet){
    			map.getCollector();
    		}
    	}
    	t.commit();
    	return topFolders.get(0);
	}
	
	public List<Specimen> getSpecimens(){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
    	SpecimenDAO specimenDao = new SpecimenDAO();
    	List<Specimen> specimens = specimenDao.findAll();
    	for(Specimen spec : specimens){
    		spec.setImageRaw(getImageRaw(spec.getImageRaw().getImageRawId()));
    		File imageFile = new File(SERVER_DIR+spec.getImageRaw().getImageRawPath()+"/"+THUMB_IMAGE_NAME_2);
    		FileDataSource dataSource = new FileDataSource(imageFile);
    		DataHandler fileDataHandler = new DataHandler(dataSource);
    		spec.setHandler(fileDataHandler);
    		spec.setCollectionCode(spec.getImageRaw().getImageRawPath());
    	}
    	t.commit();
    	return specimens;
	}
	
	public Specimen getSpecimenById(int specId){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
    	SpecimenDAO specimenDao = new SpecimenDAO();
    	Specimen spec = specimenDao.findById(specId);
    	if(spec==null) return null;
    	spec.setImageRaw(getImageRaw(spec.getImageRaw().getImageRawId()));
		File imageFile = new File(SERVER_DIR+spec.getImageRaw().getImageRawPath()+"/"+THUMB_IMAGE_NAME_2);
		FileDataSource dataSource = new FileDataSource(imageFile);
		DataHandler fileDataHandler = new DataHandler(dataSource);
		spec.setHandler(fileDataHandler);
		spec.setCollectionCode(spec.getImageRaw().getImageRawPath());
    	return spec;
	}
	
	public List<Specimen> getSpecimens2(int pageNo, int itemNoPerPage){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
    	SpecimenDAO specimenDao = new SpecimenDAO();
    	List<Specimen> specimens = specimenDao.findPage(pageNo, itemNoPerPage);
    	for(Specimen spec : specimens){
    		spec.setImageRaw(getImageRaw(spec.getImageRaw().getImageRawId()));
    		File imageFile = new File(SERVER_DIR+spec.getImageRaw().getImageRawPath()+"/"+THUMB_IMAGE_NAME);
    		FileDataSource dataSource = new FileDataSource(imageFile);
    		DataHandler fileDataHandler = new DataHandler(dataSource);
    		spec.setHandler(fileDataHandler);
    	}
    	t.commit();
    	return specimens;
	}
	
	public ImageRaw getImageRaw(int imageRawId){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
		ImageRawDAO dao = new ImageRawDAO();
		ImageRaw raw = dao.findById(imageRawId);
		File imageFile = new File(SERVER_DIR+raw.getImageRawPath()+"/"+FULL_IMAGE_NAME);
		FileDataSource dataSource = new FileDataSource(imageFile);
		DataHandler fileDataHandler = new DataHandler(dataSource);
		raw.setHandler(fileDataHandler);
		t.commit();
		return raw;
	}
	
	public User validateLogin(String username, String password){
		List<Authority> authorities = new ArrayList<Authority>();
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
		UserDAO dao = new UserDAO();
		UserAuthorityMapDAO mapDao = new UserAuthorityMapDAO();
		List<User> users = dao.findByUsername(username);
	    if(users.size()==0){
	    	t.commit();
	    	return null;
	    }
	    else{
	    	User user = users.get(0);
	    	if(user.getPassword().equals(password)==false){
	    		t.commit();
	    		return null;
	    	}
	    	else{
	    		t.commit();
	    		return user;
	    	}
	    }
	}
	
	public List<Authority> getAuthorities(int userId){
		List<Authority> authorities = new ArrayList<Authority>();
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
		UserDAO dao = new UserDAO();
		UserAuthorityMapDAO mapDao = new UserAuthorityMapDAO();
		User user = dao.findById(userId);
		List<UserAuthorityMap> maps = mapDao.findAll();
		for(UserAuthorityMap map : maps){
			if(map.getUser().getUserId()==user.getUserId()){
				authorities.add(map.getAuthority());
			}
		}
	    t.commit();
	    return authorities;
	}
	
	public Specimen insertSpecimen(
			String imgFileUrl,
			String collectorName,
			Specimen spec,
			DataHandler full,
			DataHandler full_2,
			DataHandler full_3,
			DataHandler full_4){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
    	Specimen inputSpecimen = spec;
    	FolderDAO folderDao = new FolderDAO();
    	ImageRawDAO imgRawDao = new ImageRawDAO();
    	int nameIndex = 0;
    	File folder = new File(SERVER_DIR+imgFileUrl);
    	while(folder.exists()){
    		folder = new File(SERVER_DIR+imgFileUrl+"_"+nameIndex);
    		nameIndex++;
    	}
    	folder.mkdir();
    	try{
    		ByteArrayOutputStream output = new ByteArrayOutputStream();
        	full.writeTo(output);
    		InputStream in = new ByteArrayInputStream(output.toByteArray());
    		BufferedImage src = ImageIO.read(in);
    		
    		ByteArrayOutputStream output1 = new ByteArrayOutputStream();
        	full_2.writeTo(output1);
    		InputStream in1 = new ByteArrayInputStream(output1.toByteArray());
    		BufferedImage src1 = ImageIO.read(in1);
    		
    		ByteArrayOutputStream output2 = new ByteArrayOutputStream();
        	full_3.writeTo(output2);
    		InputStream in2 = new ByteArrayInputStream(output2.toByteArray());
    		BufferedImage src2 = ImageIO.read(in2);
    		
    		ByteArrayOutputStream output3 = new ByteArrayOutputStream();
        	full_4.writeTo(output3);
    		InputStream in3 = new ByteArrayInputStream(output3.toByteArray());
    		BufferedImage src3 = ImageIO.read(in3);
    		
    		ImageIO.write(src, "JPEG", new File(folder.getAbsolutePath()+"/"+FULL_IMAGE_NAME));
    		ImageIO.write(src1, "JPEG", new File(folder.getAbsolutePath()+"/"+DISPLAY_IMAGE_NAME));
    		ImageIO.write(src2, "JPEG", new File(folder.getAbsolutePath()+"/"+THUMB_IMAGE_NAME));
    		ImageIO.write(src3, "JPEG", new File(folder.getAbsolutePath()+"/"+THUMB_IMAGE_NAME_2));
    		
    		
    	    
    	}catch(Exception e){
    		e.printStackTrace();
    	}

//    	List<Folder> topFolders = folderDao.findByProperty("folderId", "1");
    	CollectorDAO collectorDao = new CollectorDAO();
    	SpecCollectorMapDAO scmDao = new SpecCollectorMapDAO();
//    	inputSpecimen.setFolder(topFolders.get(0));
    	ImageRaw imgRaw = new ImageRaw();
    	imgRaw.setImageRawPath(folder.getName());
    	imgRawDao.attachDirty(imgRaw);
    	inputSpecimen.setImageRaw(imgRaw);
    	String nameCharArray [] = collectorName.split(" ");
    	String firstName = nameCharArray[0];
    	String lastName  = nameCharArray[nameCharArray.length-1];
    	List<Collector> collectors = collectorDao.findByName(firstName, lastName);
    	Collector collector = null;
    	SpecCollectorMap scm = null;
    	if(collectors.size()==0){
    		collector = new Collector();
    		collector.setCollectorFirstName(firstName);
    		collector.setCollectorLastName(lastName);
    		collectorDao.attachDirty(collector);
    	}
    	else collector = collectors.get(0);
    	SpecimenDAO specimenDao = new SpecimenDAO();
    	specimenDao.attachDirty(inputSpecimen);
    	
    	
    	scm = new SpecCollectorMap();
		scm.setSpecimen(inputSpecimen);
		inputSpecimen.setCollectionCode(folder.getName());
		scm.setCollector(collector);
    	scmDao.attachDirty(scm);
    	t.commit();
    	try {
	    	String host = "127.0.0.1";
		    byte[] message = (inputSpecimen.getSpecimenId()+"").getBytes();
	        InetAddress address;
			address = InetAddress.getByName(host);
			
	        
	        if(ports!=null&&ports.equals("")==false) 
	        	if(ports.contains("*")==false){
	        		DatagramPacket packet = new DatagramPacket(message, message.length,
		        			address, Integer.parseInt(ports));
		        	DatagramSocket dsocket = new DatagramSocket();
		        	dsocket.send(packet);
	        	}else{
	        		System.out.println(ports);
			        for(int i=0;i<ports.split("\\*").length;i++){
			        	DatagramPacket packet = new DatagramPacket(message, message.length,
			        			address, Integer.parseInt(ports.split("\\*")[i]));
			        	DatagramSocket dsocket = new DatagramSocket();
			        	dsocket.send(packet);
			        }
	        	}
    	} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return inputSpecimen;
	}
	
	public void updateSpecimen(Specimen spec){
		Transaction t = HibernateSessionFactory.getSession().beginTransaction();
		SpecimenDAO specimenDao = new SpecimenDAO();
    	specimenDao.merge(spec);
    	t.commit();
	}
	
	public List<Collector> getCollectorsBySpecimen(Specimen spec){
		List<Collector> collectors = new ArrayList<Collector>();
		for(SpecCollectorMap map : spec.getSpecCollectorMaps()){
			collectors.add(map.getCollector());
		}
		return collectors;
	}
	
	public void setPort(String portNumber){
		System.out.println(ports);
		if(ports==null||ports.equals("")) ports += portNumber; 
		else ports+="*"+portNumber;
	}
}
